package View;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;

import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SpringLayout;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;

import DTO.Field;
import DTO.ForeignKey;
import DTO.Row;
import DTO.Table;
import XML.XMLHelper;


public class TableTab {
	public static String colNameTemp = null;
	public static String colNameBefore = "";
	public static int rowClicked = -1;
	
	public TableTab(String tabName){
		createTab(tabName);
	}
	
	private static void createTab(String tabName) {
		// add button close tab
		JButton closeButton = new JButton("");
		final JTable table = new JTable();
		
		
		closeButton.setIcon(new ImageIcon("res\\close-icon.png"));
		closeButton.setMargin(new Insets(0, 2, 0, 1));
		closeButton.setForeground(Color.RED);
		

		final JPanel titlePanel = new JPanel();
		titlePanel.setBackground(Color.WHITE);

		JScrollPane scrollPane = new JScrollPane();
		ServerScreen.tabbedPane.addTab(tabName, null, scrollPane, null);
		titlePanel.add(new JLabel(ServerScreen.tabbedPane.getTitleAt(ServerScreen.tabbedPane
				.indexOfComponent(scrollPane))));
		System.out.println(ServerScreen.tabbedPane.indexOfComponent(scrollPane));
		titlePanel.add(closeButton);
		
		closeButton.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub

				int i = ServerScreen.tabbedPane.indexOfTabComponent(titlePanel);				
				for(int j = 0; j < ServerScreen.tableOpened.size(); j++){
					String item = (String)ServerScreen.tableOpened.elementAt(j);
					String title = ServerScreen.tabbedPane.getTitleAt(i);
					if(item.compareTo(title)==0){
						ServerScreen.tableOpened.removeElementAt(j);
						int option = JOptionPane.showConfirmDialog(ServerScreen.frame, "Do you want to save this table", "Confirm", JOptionPane.OK_CANCEL_OPTION);
						if(option == JOptionPane.OK_OPTION){
							if(table.getModel().getRowCount() == 1 && table.getModel().getValueAt(0, 2) == ""){
								JOptionPane.showMessageDialog(ServerScreen.frame, "Create Table fail!", "Error", JOptionPane.OK_OPTION);
								int position = ServerScreen.top.getChildCount();
								DefaultMutableTreeNode nod = (DefaultMutableTreeNode) ServerScreen.top.getChildAt(position-1);
								MutableTreeNode node = (MutableTreeNode)nod;
								ServerScreen.treeModel.removeNodeFromParent(node);
								ServerScreen.tabbedPane.remove(i);
							}else{
								createTableDb(title, table);
								insertField(title, table);
								ServerScreen.tabbedPane.remove(i);
								ServerScreen.reloadTree();
							}
							break;
						}else{
							if(table.getModel().getRowCount() == 1 && table.getModel().getValueAt(0, 2) == ""){
								int position = ServerScreen.top.getChildCount();
								DefaultMutableTreeNode nod = (DefaultMutableTreeNode) ServerScreen.top.getChildAt(position-1);
								MutableTreeNode node = (MutableTreeNode)nod;
								ServerScreen.treeModel.removeNodeFromParent(node);
							}
							
							ServerScreen.tabbedPane.remove(i);
							break;
						}
					}
				}
				
			}
			
		});
		ServerScreen.tabbedPane.setTabComponentAt(ServerScreen.tabbedPane.indexOfComponent(scrollPane),
				titlePanel);
		
		createTable(table, scrollPane, tabName);
		
	}
	
	private static void createTable(final JTable table, JScrollPane scrollPane, final String tabName) {
		

		table.setSurrendersFocusOnKeystroke(true);
		table.setColumnSelectionAllowed(true);
		table.setFont(new Font("Tahoma", Font.PLAIN, 13));
		scrollPane.setViewportView(table);

		ServerScreen.springLayout.putConstraint(SpringLayout.NORTH, table, 99,
				SpringLayout.NORTH, ServerScreen.frame.getContentPane());
		ServerScreen.springLayout.putConstraint(SpringLayout.WEST, table, 36,
				SpringLayout.EAST, ServerScreen.tabbedPane);
		ServerScreen.springLayout.putConstraint(SpringLayout.SOUTH, table, 0,
				SpringLayout.SOUTH, ServerScreen.tabbedPane);
		table.setCellSelectionEnabled(true);

		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
		table.getTableHeader().setReorderingAllowed(false);

		table.setModel(new DefaultTableModel(new Object[][] { { null, "", "",
				false}, }, new String[] { "", "Column Name", "Data Type",
				"Allow Nulls"}) {
			Class[] columnTypes = new Class[] { ImageIcon.class, String.class,
					Object.class, Boolean.class};

			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}

			@Override
			public boolean isCellEditable(int row, int column) {
				// TODO Auto-generated method stub
				switch(column){
				case 0:
					return false;
				default:
					return true;
				}
			}
		});

		table.setRowHeight(20);
		table.getColumnModel().getColumn(0).setPreferredWidth(30);
		table.getColumnModel().getColumn(1).setPreferredWidth(160);
		table.getColumnModel().getColumn(2).setPreferredWidth(160);
		

		String[] values = new String[] { "int", "String"};
		
		
		JComboBox com = new JComboBox(values);

		//com.setEditable(true);


		DefaultCellEditor de = new DefaultCellEditor(com);
		table.getColumnModel()
				.getColumn(table.getColumnModel().getColumnIndex("Data Type"))
				.setCellEditor(de);
		//table.getColumnModel()
		//		.getColumn(table.getColumnModel().getColumnIndex(""))
		//		.setCellRenderer(new TableButton(""));
		//table.getColumnModel()
		//		.getColumn(table.getColumnModel().getColumnIndex(""))
		//		.setCellEditor(tableButton);
		
		
		table.setFillsViewportHeight(true);
		//table.addMouseListener(tableListener);
		table.addMouseListener(new MouseListener(){

			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
				int row = table.rowAtPoint(e.getPoint());
				int col = table.columnAtPoint(e.getPoint());
				if(row != -1 && col != -1){
					
					colNameBefore = String.valueOf(table.getValueAt(row, col));
					
					if(XMLHelper.IsExist(ServerScreen.database.getName(), tabName)){
						int fieldSize = ServerScreen.database.getTableByName(tabName).get_Fields().size();
						for(int i = 0; i < fieldSize; i++){
							if(i == row)
								JOptionPane.showMessageDialog(ServerScreen.frame, "Change in this row will be unsaved!", "Alert", JOptionPane.OK_OPTION);
						}
						
						if(row >= fieldSize){
							if(col == 0){
								if(String.valueOf(table.getValueAt(row, 1)).compareTo("") != 0){
									if(String.valueOf(table.getValueAt(row, col)).compareTo("null") == 0){
										table.setValueAt(new ImageIcon("res\\Key-icon-min.png"), row, col);
									}else{
										table.setValueAt(null, row, col);
									}
								}
							}
						}
						
					}else{
						if(col == 0){
							if(String.valueOf(table.getValueAt(row, 1)).compareTo("") != 0){
								if(String.valueOf(table.getValueAt(row, col)).compareTo("null") == 0){
									table.setValueAt(new ImageIcon("res\\Key-icon-min.png"), row, col);
								}else{
									table.setValueAt(null, row, col);
								}
							}
						}
					}
					
				}
				
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mouseExited(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mousePressed(MouseEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				// TODO Auto-generated method stub
				int row = table.rowAtPoint(e.getPoint());
				int col = table.columnAtPoint(e.getPoint());
				rowClicked = row;
				System.out.println(rowClicked);
			}
			
		});

		JPopupMenu popupMenu = new JPopupMenu();
		addPopup(table, popupMenu);

		JMenuItem mntmDeleteRow = new JMenuItem("Delete");
		mntmDeleteRow.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				int count = 0;
				if(XMLHelper.IsExist(ServerScreen.database.getName(), tabName)){
					int fieldSize = ServerScreen.database.getTableByName(tabName).get_Fields().size();
					for(int i = 0; i < fieldSize; i++){
						if(i == rowClicked){
							JOptionPane.showMessageDialog(ServerScreen.frame, "Change in this row will be unsaved!", "Alert", JOptionPane.OK_OPTION);
						}else{
							count++;
						}
					}
					if(count == fieldSize){
						if(rowClicked != table.getRowCount() - 1){
							int option = JOptionPane.showConfirmDialog(ServerScreen.frame, "Do you want to delete row num " + rowClicked  + " ?", "Delete Row", JOptionPane.OK_CANCEL_OPTION);
							if(option == JOptionPane.OK_OPTION){
								DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
								tableModel.removeRow(rowClicked);
							}
						}
					}
					System.out.println("exist");
				}else{
					if(rowClicked != table.getRowCount() - 1){
						int option = JOptionPane.showConfirmDialog(ServerScreen.frame, "Do you want to delete row num " + rowClicked  + " ?", "Delete Row", JOptionPane.OK_CANCEL_OPTION);
						if(option == JOptionPane.OK_OPTION){
							DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
							tableModel.removeRow(rowClicked);
							//JOptionPane.showMessageDialog(ServerScreen.frame, "");
						}else{
							
						}
					}
				}
				
			}
			
		});
		popupMenu.add(mntmDeleteRow);

		DefaultTableModel model = (DefaultTableModel) table.getModel();
		//model.addTableModelListener(modelListener);
		model.addTableModelListener(new TableModelListener(){

			@Override
			public void tableChanged(TableModelEvent e) {
				// TODO Auto-generated method stub
				int firstRow = e.getFirstRow();
				int lastRow = e.getLastRow();
				int col = e.getColumn();
				int colName = table.getColumnModel().getColumnIndex("Column Name");
				int colData = table.getColumnModel().getColumnIndex("Data Type");
				int colNull = table.getColumnModel().getColumnIndex("Allow Nulls");

				if(col != -1){
					for(int i = firstRow; i <= lastRow; i++){
						TableModel model = (TableModel)e.getSource();
						Object data = model.getValueAt(i, col);
						System.out.println("Data la: " + data);
						deleteRowTable(table);
						if(data != null && !data.equals("")){
							
							System.out.println("Current row: "+ i);
							
							if(model.getColumnName(col).compareTo("Column Name") == 0){
								
								if(data.toString().compareTo(formatString((String)data)) != 0){
									colNameTemp = formatString((String)data);
									model.setValueAt(colNameTemp, i, colName);
									break;
								}	
								
								if(isColumnNameExist(table, i, tabName, data.toString()) == false){
									
									if(model.getValueAt(i, colData).equals(""))
										model.setValueAt("String", i, colData);
									if(model.getValueAt(i, colNull).toString().compareTo("false") == 0)
										model.setValueAt(true, i, colNull);
									
									if(formatString((String)data) != "")
										insertRowTable(table);
								}else{
									JOptionPane.showMessageDialog(ServerScreen.frame, data + " exists!", "Error", JOptionPane.OK_OPTION);
									model.setValueAt(colNameBefore, i, colName);				
								}
								break;

							}
							if(model.getColumnName(col).compareTo("Allow Nulls") == 0){
								if(model.getValueAt(i, colData).equals("")){
									model.setValueAt("String", i, colData);
								}
								/*if(colNameTemp != null){
									model.setValueAt(colNameTemp, i, colName);
									colNameTemp = null;
								}*/
								//insertRowTable(table);
								break;
							}
							if(model.getColumnName(col).compareTo("Data Type") == 0){
								if(model.getValueAt(i, colNull).toString().compareTo("false") == 0)
									model.setValueAt(true, i, colNull);
								/*if(colNameTemp != null){
									model.setValueAt(colNameTemp, i, colName);

									colNameTemp = null;
								}*/
								//insertRowTable(table);
								break;
							}
							break;
						}else{
							if(model.getColumnName(col).compareTo("Column Name") == 0){
								if(i != table.getRowCount() - 1){
									DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
									
									tableModel.removeRow(i);
									break;
								}
							}
						}
						
					}
				}
			}
			
		});
		loadFields(table, tabName);
	}
	
	private static void loadFields(JTable table, String tabName){
		//Vector<Field> fields = XMLHelper.GetListOfField(ServerScreen.database.getName(), tabName);
		
		Table tableDb = ServerScreen.database.getTableByName(tabName);
		if(tableDb != null){
			Vector<Field> fields = tableDb.get_Fields();
			DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
			

			for(int i = 0; i < fields.size(); i++){					
				Field field = fields.elementAt(i);
				String name = field.get_Name();
				
				int type = field.get_Type();
				String typeData;
				if(type == 0)
					typeData = "int";
				else
					typeData = "String";
				
				boolean primary = field.is_IsPrimaryKey();
				ImageIcon primaryIcon = null;
				if(primary == true){
					primaryIcon = new ImageIcon("res\\Key-icon-min.png");
				}
				
				boolean notNulls = field.is_NotNull();
				ForeignKey foreign = field.get_ForeignKey();
				
				tableModel.insertRow(i, new Object[]{primaryIcon, name, typeData, notNulls, foreign});

			}
			
		}
	}
	
	private static void createTableDb(String tableName, JTable table){
		if(ServerScreen.database.getTableByName(tableName) == null){
			Vector<Field> fields = new Vector<Field>();
			
			for(int i = 0; i < table.getModel().getRowCount() - 1; i++){
				boolean primary = false;
				if(String.valueOf(table.getModel().getValueAt(i, 0)).compareTo("null") == 0)
					primary = false;
				else 
					primary = true;
				
				String name = (String)table.getModel().getValueAt(i, 1);
				int type = 0;
				if(table.getModel().getValueAt(i, 2).toString().compareTo("int") == 0)
					type = 0;
				if(table.getModel().getValueAt(i, 2).toString().compareTo("String") == 0)
					type = 1;
				
				boolean notNulls = false;
				if(table.getModel().getValueAt(i, 3).toString().compareTo("false") == 0)
					notNulls = false;
				else 
					notNulls = true;
				ForeignKey foreignKey = new ForeignKey("", "", "");
				
				Field field = new Field(name, notNulls, type, primary, foreignKey);
				fields.add(field);
			}
			
			Vector<Row> rows = new Vector<Row>();
			Table tableDb = new Table(tableName, ServerScreen.database.getName(), fields, rows);
			XMLHelper.CreateTableData(ServerScreen.database.getName(), tableName, rows);
			ServerScreen.database.addTable(tableDb);
		}else{
			//table da ton tai, nhiem vu la duyet tung row trong table
			//thuc hien trong tablechanged event
		}
	}
	
	private static String formatString(String input){
		String output = "";
		int begin = 0, end = input.length()-1;
		for(int i = 0; i < input.length(); i++){
			if(input.charAt(i) != ' '){
				begin = i;
				break;
			}
		}
		
		for(int i = input.length() - 1; i >= 0; i--){
			if(input.charAt(i) != ' '){
				end = i;
				break;
			}
		}
		
		if(input.charAt(begin) == ' ')
			output = "";
		else
			output = input.substring(begin, end + 1);

		if(output != ""){
			output = output.toLowerCase();
		}
		
		return output;
	}
	
	private static void deleteRowTable(JTable table){
		DefaultTableModel modelTable = (DefaultTableModel) table.getModel();
		for(int i = 0; i < table.getRowCount() - 1; i++){
			if(table.getValueAt(i, 1).toString().compareTo("") == 0
					&& table.getValueAt(i, 2).toString().compareTo("") == 0)
				modelTable.removeRow(i);
		}
	}
	
	private static void insertRowTable(JTable table){
		
		int colData = table.getColumnModel().getColumnIndex("Data Type");

		System.out.println("last row: " + String.valueOf(table.getRowCount() - 1));
		System.out.println("insert row: " + table.getValueAt(table.getRowCount() - 1, colData));
		if(!(table.getValueAt(table.getRowCount() - 1, colData).equals("")))
		{
			DefaultTableModel modelTable = (DefaultTableModel) table.getModel();
			modelTable.insertRow(table.getRowCount(), new Object[]{null, "", "", false});
		}
	}
	
	/*
	 * insert new row into xml file
	 */
	
	private static void insertField(String tableName, JTable table){
		if(XMLHelper.IsExist(ServerScreen.database.getName(), tableName)){
			String name;
			boolean notNulls;
			int type;
			boolean isPrimaryKey;
			ForeignKey foreignKey;
			int fieldCountInDb = ServerScreen.database.getTableByName(tableName).get_Fields().size();
			for(int i = fieldCountInDb; i < table.getRowCount() - 1; i++){
				name = table.getValueAt(i, table.getColumnModel().getColumnIndex("Column Name")).toString();
				if(name.compareTo("") != 0){
					notNulls = (Boolean) table.getValueAt(i, table.getColumnModel().getColumnIndex("Allow Nulls"));
					if(String.valueOf(table.getValueAt(i, table.getColumnModel().getColumnIndex("Data Type"))).compareTo("int") == 0)
						type = 0;
					else
						type = 1;
					
					if(String.valueOf(table.getValueAt(i, 0)).compareTo("null")==0)
						isPrimaryKey = false;
					else{
						isPrimaryKey = true;
					}
					
					foreignKey = new ForeignKey("", "", "");
					
					Field field = new Field(name, notNulls, type, isPrimaryKey, foreignKey);
					XMLHelper.InsertField(ServerScreen.database.getName(), tableName, field);
				}
			}	
		}
	}
	
		
	/*
	 * delete Row
	 */

	private void deleteField(MouseEvent e) {

	}

	/*
	 * update Row
	 */

	private void updateField(String columnName) {
		
	}
	
	/*
	 * Kiem tra column name field da ton tai hay chua ^_^
	 */
	private static boolean isColumnNameExist(JTable table, int row, String tableName, String columnName){
		for(int i = 0; i < table.getRowCount(); i++){
			String colName = (String)table.getValueAt(i, table.getColumnModel().getColumnIndex("Column Name"));
			if(i != row)
				if(colName.compareTo(columnName) == 0)
					return true;
		}
		return false;
	}
	
	/*
	 * Kiem tra trong table co field nao column name == "" hay ko
	 */
	
	
	
	private static void addPopup(Component component, final JPopupMenu popup) {
		component.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			private void showMenu(MouseEvent e) {
				popup.show(e.getComponent(), e.getX(), e.getY());
			}
		});
	}
}
